#include 	"ZiaServerUnix.h"
#include	"../../parser/RequestParser.hpp"
#include	"../../Api Headers/DataTree.hpp"
#include	"../../requests/Request.h"
#include	"../../CrossThread/ManipList.hpp"
#include	<fstream>
#include	<utility>
// Constructor / Destructor

using namespace std;
extern ManipList<std::pair<std::string, int> >		msgList;

// Constructor / Destructor

ZiaServerUnix::ZiaServerUnix()
{
}

ZiaServerUnix::~ZiaServerUnix()
{

}




// Public Methods

void		ZiaServerUnix::LaunchServ()
{
  if (ConfigNListen() >= 0)
    SelectLoop();
}

// Private Methods

int	ZiaServerUnix::ConfigNListen()
{
	struct sockaddr_in	addr;
	
	addr.sin_family = AF_INET;
	addr.sin_port = htons(PORT);
	addr.sin_addr.s_addr = INADDR_ANY;
	_servSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (_servSock < 0)
	    return (-1);
	if (bind(_servSock, (struct sockaddr *)&addr, sizeof(addr)) == -1)
	  {
	    std::cout << "Bind Failed\n" << std::endl;
	    return (-2);
	  }
	listen(_servSock, SOMAXCONN);
	return (0);
}

int	ZiaServerUnix::SelectLoop()
{
	fd_set				StaticRFdSet;
	fd_set				RFdSet;
	int					max = _servSock;
	int					checkSock;

	FD_ZERO(&StaticRFdSet);
	FD_SET(_servSock, &StaticRFdSet);
	std::cout << "BEFORE" << std::endl;
	for (;;)
	{
	  RFdSet = StaticRFdSet;
	  if (select(max + 1, &RFdSet, NULL, NULL, NULL) < 1)
	    std::cout << "Select Error" << std::endl;
	  for(checkSock = 0; checkSock < max + 1; checkSock++)
	    {
	      if (FD_ISSET(checkSock, &RFdSet)) 
		{
		  if (checkSock == _servSock)
		    max = NewCliSocket(&StaticRFdSet, max);
		  else
		    {
		      std::cout << "Message Received:\n";
		      IncomingMsg(checkSock, &StaticRFdSet, &max);
		    }
		}
	    }
	}
	return (0);
}

int			ZiaServerUnix::NewCliSocket(fd_set *StaticRFdSet, int max)
{
	socklen_t					lenCliAddr = sizeof(struct sockaddr_in);
	struct sockaddr_in	cliAddr;
	int					cliSock;

	cliSock = accept(_servSock, (struct sockaddr *)&cliAddr, &lenCliAddr);
	FD_SET(cliSock, StaticRFdSet);
	if (max < cliSock)
		max = cliSock;
	return (max);
}

std::string	ZiaServerUnix::IncomingMsg(int checkSock, fd_set *StaticRFdSet, int *max)
{
	std::string			msg = "";
	int					it = 0;
	int					reading;
	char				buf[BUFLEN + 1];
	int					max_old;
	std::pair<std::string, int>	*myRequest;

	msg.clear();
	reading = BUFLEN;
	while ((reading = recv(checkSock, buf, BUFLEN, MSG_DONTWAIT)) > 0)
	{
	  buf[reading] = '\0';
	  msg.insert(it, buf, reading);
	  it += reading;
	}
//	std::cout << "Message : " << msg.c_str() << std::endl;
	myRequest = new std::pair<std::string, int>;
	myRequest->first = msg;
	myRequest->second = checkSock;
	cout << "TEST" << endl;
	msgList.addMessage(myRequest);
	cout << "TESTEND" << endl;
// 	zia::Connection		co;
// 	co.StockCliSock(checkSock);
	/* 
	mettre dans une instance message
	envois instance message au parseur
	*/
	FD_CLR(checkSock, StaticRFdSet);
	if (checkSock == *max)
	  {
	    max_old = *max;
	    *max = 0;
	    for (checkSock = 0; checkSock < max_old ; checkSock++)
	      if ((checkSock > *max) && (FD_ISSET(checkSock, StaticRFdSet)))
		*max = checkSock;
	  }
	return (msg);
}
void		ZiaServerUnix::closeConnection()
{
	if (_servSock)
		close(_servSock);
}
